import * as fs from "fs";
import watch from "node-watch";
import * as path from "path";
import { errors } from "./errors";
import { compileFile as bielCompileFile } from "./actions/biel-compile";
import copyFile from "./actions/copy-file";
import { FileAction } from "../types";

const skipFiles = ["\\S+\\.d\\.tsx?$", "\\S+\\.test\\.tsx?$", "\\S+\\.spec\\.tsx?$"]
const extCopy = [".js", ".html", ".css", ".jpg", ".png", ".gif", ".scss", ".less"];

let fileActions: { [ext: string]: FileAction } = {
    ".ts": bielCompileFile,
    ".tsx": bielCompileFile,
}

extCopy.forEach(ext => fileActions[ext] = copyFile);

/** 将 sourceDir 目录下所有文件生成到 outDir */
export function generateCode(sourceDir: string, outDir: string, projectPath: string,
    callback?: (filePath: string, outDir: string, projectPath: string) => void
) {

    if (!sourceDir) throw errors.argumentNull("sourceDir");
    if (!outDir) throw errors.argumentNull("outDir");
    if (!projectPath) throw errors.argumentNull("projectPath");

    if (!fs.existsSync(sourceDir))
        throw errors.pathNotExists(sourceDir);

    let files = fs.readdirSync(sourceDir);
    for (let file of files) {
        let filePath = path.join(sourceDir, file);
        if (!fs.statSync(filePath).isFile()) {
            continue;
        }

        let isSkip = isIgnoredFile(filePath);//skipFiles.some(pattern => new RegExp(pattern).test(filePath));
        if (isSkip) {
            console.log(`Skip ${filePath}`);
            continue;
        }

        let ext = extname(file);
        let action = fileActions[ext];
        if (action) {
            action(filePath, outDir, projectPath);
            if (callback) {
                callback(filePath, outDir, projectPath);
            }
        }
    }

    let dirs = fs.readdirSync(sourceDir);
    for (let dir of dirs) {
        let fullPath = path.join(sourceDir, dir);
        let outDirPath = path.join(outDir, dir);
        if (fs.statSync(fullPath).isDirectory()) {
            generateCode(fullPath, outDirPath, projectPath);
        }
    }
}

/** 监听 sourceRoot 目录下所有文件变化，并生成到 outRoot */
export function watchDirectory(sourceRoot: string, outRoot: string, projectPath: string, callback?: (filePath: string, outDir: string, projectPath: string) => void) {
    if (!sourceRoot) throw errors.argumentNull("sourceRoot");
    if (!outRoot) throw errors.argumentNull("outRoot");
    if (!projectPath) throw errors.argumentNull("projectPath");

    watch(sourceRoot, { recursive: true }, async (evt, name) => {
        let action = fileActions[extname(name)];
        let outPath = path.dirname(name).replace(sourceRoot, outRoot);
        if (!action) {
            return;
        }

        try {
            action(name, outPath, projectPath);
            if (callback)
                callback(name, outPath, projectPath);
        }
        catch (e) {
            console.error(e);
        }
    })
}

// export function copyFile(filePath: string, outDir: string) {
//     if (!filePath) throw errors.argumentNull("filePath");
//     if (!outDir) throw errors.argumentNull("outDir");

//     let out = filePath.replace(path.dirname(filePath), outDir);
//     let outDirPath = path.resolve(out, "..");

//     fs.mkdirSync(outDirPath, { recursive: true });

//     fs.copyFileSync(filePath, out);
// }

export function isIgnoredFile(filePath: string) {
    if (!filePath) throw errors.argumentNull("filePath");

    let isSkip = skipFiles.some(pattern => new RegExp(pattern).test(filePath));
    return isSkip;
}

function extname(file: string) {
    // let ext = /\.[a-zA-Z]+/.exec(file)?.[0] || '';
    let ext = path.extname(file);
    return ext;
}

